#include <stdio.h>
#include <stdlib.h>
#include "double_list.h"

#if defined(_DOUBLE_LIST_VER2)

struct d_node
{
    struct d_node *prev;
    struct d_node *next;

    int elem;
};

_DNode *create_node(void)
{
    _DNode *new_node = NULL;

    new_node = (_DNode *)malloc(sizeof(_DNode));
    if (NULL == new_node)
    {
	return NULL;
    }

    new_node->prev = NULL;
    new_node->next = NULL;
    new_node->elem = 0;

    return new_node;
}

int init_node(_DNode *node, const void *arg)
{
    if (NULL == node)
    {
	return -1;
    }
    
    node->elem = (int)arg;
    return 0;
}

int destroy_node(_DNode *node)
{
    if (NULL == node)
    {
	return -1;
    }

    free(node);
    return 0;
}

_DList create_list(void)
{
    _DList new_list = NULL;

    new_list = (_DList)malloc(sizeof(* new_list));
    if (NULL == new_list)
    {
	return NULL;
    }

    new_list->next = NULL;
    new_list->prev = NULL;
    new_list->elem = 0;

    return new_list;
}

int flush_list(_DList head)
{
    _DNode *tmp = NULL;

    if (NULL == head)
    {
	return -1;
    }

    tmp = head->next;
    for(tmp; tmp != NULL; tmp = head->next)
    {
	head->next = tmp->next;
	free(tmp);
	tmp = NULL;
    }

    return 0;
}

int insert_to_list(_DList head, _DNode *node)
{
    if (NULL == head || NULL == node)
    {
	return -1;
    }
    
    if (NULL == head->next)
    {
	head->next = node;
	node->prev = head;
	return 0;
    }

    node->next = head->next;
    head->next->prev = node;
    node->prev = head;
    head->next = node;
    
    return 0;
}

int delete_node(_DList head, void *key)
{
    _DNode *del = NULL;
    _DNode *tmp = NULL;

    if (NULL == head)
    {
	return -1;
    }

    del = head->next;
    for (del; del != NULL; del = del->next)
    {
	if (del->elem == (int)key)
	{
	    tmp = del->next;
	    if (del->next == NULL)
	    {
		del->prev->next = NULL;
		free(del);
		del = NULL;
		//continue;
		break;
	    }

	    del->prev->next = del->next;
	    del->next->prev = del->prev;
	    free(del);
	    del = tmp->prev;
	    continue;
	}
    }

    return 0;
}

void print_list(_DList head)
{
    _DNode *tmp = NULL;

    if (NULL == head)
    {
	return;
    }

    for(tmp = head->next; NULL != tmp; tmp = tmp->next)
    {
	printf("%d\n", tmp->elem);
    }

    return;
}

int for_each_node(_DList head, void *(*func)(void *))
{
    _DNode *tmp = NULL;

    if (NULL == head)
    {
	return -1;
    }

    for (tmp = head->next; NULL != tmp; tmp = tmp->next)
    {
	func((void *)tmp);	/*Here we need to check the return value*/
    }

    return 0;
}

#endif
